package com.colin.util.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.regex.Pattern;

/**
 * 金额操作工具类
 * 避免代码中直接使用+，-，*，/
 */
public class AmountUtils {
    /**
     * 提供默认精度10
     */
    private static final int DEFAULT_SCALE = 2;

    /**
     * 两个double类型的数值相加
     */
    public static double add(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.add(b2).doubleValue();
    }

    /**
     * 两个String类型的数值相加
     */
    public static String add(String v1, String v2){
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.add(b2).toString();
    }

    /**
     * 相减
     */
    public static double sub(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 相减
     */
    public static double sub(String v1, String v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 相乘，此处默认保留两位小数
     * 并使四舍五入原则取值
     */
    public static double mul(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.multiply(b2).setScale(DEFAULT_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 相除，此处默认保留两位小数
     * 并使四舍五入原则取值
     */
    public static double div(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.divide(b2, DEFAULT_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
    /**
     * 两数相除
     * @param scale 指定保留小数位数
     */
    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("精度指定错误,请指定一个>=0的精度");
        }
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 对传入金额做四舍六入五成双处理
     */
    public static BigDecimal carry(BigDecimal money) {
		final String string = money.toString();
		final int point = string.indexOf('.');
		if (point == -1) {
            // 没有小数点
			return money;
		} else if (string.length() - 1 < point + 3) {
            // 小数不足3位
			return money;
		} else {
			final char milli = string.charAt(point + 3);
			if (milli < '5') {
                // 第3位小于5, 保留2位
				return new BigDecimal(string.substring(0, point + 3));
			} else if (milli > '5'){
                // 第3位大于6, 进位
				return new BigDecimal(string.substring(0, point + 3)).add(new BigDecimal("0.01"));
			} else {
                // 第3位是5
				final char cent = string.charAt(point + 2);
				if (((cent - '0') & 1) == 0) {
                    // 第2位是偶数, 不进位
					return new BigDecimal(string.substring(0, point + 3));
				} else {
                    // 第2位是奇数, 进位
					return new BigDecimal(string.substring(0, point + 3)).add(new BigDecimal("0.01"));
				}
			}
		}
	}

    /**
     * 将dubbo类型转为string类型
     * 格式化金额，统一保留0到2位小数
     */
	public static String formatAmount(Double amount){
        NumberFormat nf = NumberFormat.getInstance();
        //设置最大保留小数位数
        nf.setMaximumFractionDigits(DEFAULT_SCALE);
        //取消','等计数方式
        nf.setGroupingUsed(false);
        return nf.format(amount);
    }

    /**
     * 金额校验
     * 必须为小数点后2位
     */
    public static boolean isNormalAmount(String str) {
        //判断是否位有效数字
        Double money = null;
        try{
            money = Double.parseDouble(str);
        }catch (Exception e){
            return false;
        }
        //金额必须大于0
        if(money <= 0){
            return false;
        }
        //判断小数点后2位以内的数字的正则表达式
        return Pattern.matches("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$", str);
    }

    /**
     * 将dubbo类型转为string类型
     * 格式化金额，统一保留有且仅有2位小数
     */
    public static String formatAmount2s(Double amount){
        DecimalFormat df = new DecimalFormat("#0.00");
        return df.format(amount);
    }

    public static void main(String[] args) {
        double a = 11211113213232D;
        //1.1211113213232E13
        System.out.println(a);
        //11211113213232.00
        System.out.println(formatAmount2s(a));
        //11211113213232
        System.out.println(formatAmount(a));
        
    }

}
